home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / uupc.lzh / uupc / dcpgpkt.c < prev    next >
C/C++ Source or Header  |  1990-01-16  |  16KB  |  727 lines

  1. /*    dcpgpkt.c
  2.  *
  3.  *    Revised edition of dcp
  4.  *
  5.  *    Stuart Lynne May/87
  6.  *
  7.  *    Copyright (c) Richard H. Lamb 1985, 1986, 1987
  8.  *    Changes Copyright (c) Stuart Lynne 1987
  9.  *
  10.  *    $Id: dcpgpkt.c,v 1.2 90/01/16 10:25:07 crash Exp Locker: crash $
  11.  */
  12.  
  13. #ifndef lint
  14. static char RCSid[] = "$Id: dcpgpkt.c,v 1.2 90/01/16 10:25:07 crash Exp Locker: crash $";
  15. #endif /* lint */
  16.  
  17. /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987
  18.  *
  19.  *    3-window "g" ptotocol
  20.  *
  21.  *    Thanks go to John Gilmore for sending me a copy of Greg Chesson's
  22.  *    UUCP protocol description -- Obviously invaluable.
  23.  *
  24.  *    Thanks also go to Andrew Tannenbaum for the section on Sliding window
  25.  *    protocols with a program example in his "Computer Networks" book.
  26.  */
  27.  
  28. #include "dcp.h"
  29. #define PKTSIZE         64
  30. #define PKTSIZ2         2
  31. #define HDRSIZE         6
  32. #define MAXTRY          4
  33.  
  34. #define MAXERR  200        /* Dont want to quit in a middle of a long file*/
  35. #define TIMEOUT 4        /* could be longer */
  36. #define KPKT    1024/PKTSIZE
  37. #define POK     -1
  38.  
  39. #define SWINDOW 3    /* fixed now, U make it variable */
  40. #define RWINDOW 3
  41. #define NBUF    8   /* always SAME as MAXSEQ ? */
  42. #define MAXSEQ  8
  43.  
  44. #define between(a,b,c) ((a<=b && b<c) || (c<a && a<=b) || (b<c && c<a))
  45.  
  46. /* packet defin */
  47. static int    rwl, swl, swu, rwu, nerr, nbuffers, npkt, irec, timeout;
  48. static int    GOT_SYNC, GOT_HDR;
  49. static int    fseq[NBUF], outlen[NBUF], inlen[NBUF], arr[NBUF];
  50. static char    outbuf[NBUF][PKTSIZE+1], inbuf[NBUF][PKTSIZE+1];
  51. static unsigned char    grpkt[HDRSIZE+1];
  52. static long    ftimer[NBUF], acktmr, naktmr;
  53.  
  54. /******************SUB SUB SUB PACKET HANDLER************/
  55. gopenpk()
  56. {
  57.     int    i, j, n1, n2, len;
  58.     char    tmp[PKTSIZE+1];
  59.     pktsize = PKTSIZE; /* change it later after the init */
  60.     msgtime = MSGTIME; /* not sure I need this for "g" proto */
  61.     /* initialize proto parameters */
  62.     swl = nerr = nbuffers = npkt = 0;
  63.     swl = swu = 1;
  64.     rwl = 0;
  65.     rwu = RWINDOW - 1;
  66.     for (i = 0; i < NBUF; i++) {
  67.         ftimer[i] = 0;
  68.         arr[i] = FALSE;
  69.     }
  70.     GOT_SYNC = GOT_HDR = FALSE;
  71.     /* 3-way handshake */
  72.     timeout = 1; /* want some timeout capability here */
  73.     gspack(7, 0, 0, 0, tmp);
  74. rsrt:
  75.     if (nerr >= MAXERR)
  76. #if 1
  77.         printmsg( 0, "excessive errors (%d) at pkt %d", nerr, npkt );
  78.         nerr = 0;
  79. #else
  80.         return(-1);
  81. #endif
  82.     /*
  83.      *    INIT sequence.  Easy fix for variable pktsize and windows.
  84.      *    I didn't since all the machines I talk to use W=3 PKTSZ=64
  85.      *
  86.      *    If you do this make sure to reflect the changes in "grpack"
  87.      *    and "gspack".
  88.      */
  89.     switch (i = grpack(&n1, &n2, &len, tmp)) {
  90.     case 7:
  91.         gspack(6, 0, 0, 0, tmp);
  92.         goto rsrt;
  93.     case 6:
  94.         gspack(5, 0, 0, 0, tmp);
  95.         goto rsrt;
  96.     case 5:
  97.         break;
  98.     default:
  99.         nerr++;
  100.         printmsg(4, "error #%d (%d) at pkt %d", nerr, i, npkt);
  101.         printmsg(5, "   grpack(%d, %d, %d, :%s:)", n1,n2,len, prt(tmp,len));
  102.         gspack(7, 0, 0, 0, tmp);
  103.         goto rsrt;
  104.     }
  105.     nerr = 0;
  106.     return(0);      /* channel open */
  107. }
  108.  
  109.  
  110. gclosepk()
  111. {
  112.     int    i;
  113.     char    tmp[PKTSIZE+1];
  114.  
  115.     timeout = 1;
  116.     for (i = 0; i < MAXTRY; i++) {
  117.         gspack(CLOSE, 0, 0, 0, tmp);
  118.         if (gmachine() == CLOSE)
  119.             break;
  120.     }
  121.     printmsg( 0, "number of errors %d and pkts xfered %d", nerr, npkt );
  122.     return(0);
  123. }
  124.  
  125. /*
  126.  *    ggetpkt
  127.  *
  128.  *    description:
  129.  *        Gets no more than a packet's worth of data from the "packet i/o
  130.  *        state machine".  May have to periodically run the pkt machine to
  131.  *        get some packets.
  132.  *
  133.  *    on input: dont care
  134.  *        getpkt( char *data, int *len)
  135.  *
  136.  *    on return: data+\0 and length in len.
  137.  *        ret(0)  if all's well
  138.  *        ret(-1) if problems (fail)
  139.  */
  140.  
  141. ggetpkt(cdata, len)
  142. int    *len;
  143. char    cdata[];
  144. {
  145.     int    i2;
  146.  
  147.     irec = 1;
  148.     timeout = 0;
  149.  
  150.     /* WAIT FOR THE DESIRED PACKET */
  151.     while ((arr[rwl]) == FALSE)
  152.         if (gmachine() != POK)
  153.             return(-1);
  154.  
  155.     /* GOT A PKT ! */
  156.     i2 = rwl;                    /* <-- mod(,rwindow) for > 8 seq no.s */
  157.     *len = inlen[i2];
  158.     memcpy(cdata, inbuf[i2], *len);
  159.     arr[i2] = FALSE;
  160.     rwu = (1 + rwu) % MAXSEQ;    /* bump rec window */
  161.     npkt++;
  162.     return(0);
  163. }
  164.  
  165.  
  166. /*
  167.  *
  168.  *  gsendpkt
  169.  *
  170.  *    description:
  171.  *        Put at most a packet's worth of data in the pkt state
  172.  *            machine for transmission.
  173.  *        May have to run the pkt machine a few times to get
  174.  *            an available output slot.
  175.  *
  176.  *    on input: gsendpkt(char *data, int len, int flg)
  177.  *        len=length of data in data.
  178.  *        flg=2 just send the packet with no wait for ack.
  179.  *        flg>0 zero out the unused part of the buffer. (for UUCP "msg" pkts)
  180.  *        flg=0 normal data
  181.  *
  182.  *    return:
  183.  *        ret(0) if alls well
  184.  *        ret(-1) if problems (fail)
  185.  */
  186.  
  187. gsendpkt(cdata, len, flg)
  188. int    len, flg;
  189. char    *cdata;
  190. {
  191.     int    i, i1;
  192.     long    ttmp;
  193.  
  194.     irec = 0;
  195.     timeout = 0;            /* non-blocking reads */
  196.  
  197.     /*
  198.      *    WAIT FOR INPUT i.e. if we've sent SWINDOW pkts and none have been
  199.      *    acked, wait for acks
  200.      */
  201.     while (nbuffers >= SWINDOW)
  202.         if (gmachine() != POK)
  203.             return(-1);
  204.  
  205.     i1 = swu;                /* <-- mod(,rwindow) for > 8 seq no.s */
  206.  
  207.     /*
  208.      *    PLACE PACKET IN TABLE AND MARK UNACKED
  209.      *    fill with zeros or not
  210.      *
  211.      *    [FJE] Changed to use memcpy/memset instead of strcpy!
  212.      */
  213.     if (flg) {
  214.         if (!len)            /* Currently, all flg!=0 calls are len==0 */
  215.             len = strlen(cdata);
  216.         memcpy(outbuf[i1], cdata, len);
  217.         memset(outbuf[i1]+len, (int) '\0', PKTSIZE-len);
  218.         i = len = PKTSIZE;
  219.     } else {                /* flg==0 only inside sdata() */
  220.         memcpy(outbuf[i1], cdata, len);
  221.         outbuf[i1][len] = '\0';
  222.     }
  223.     /* mark packet */
  224.     outlen[i1] = len;
  225.     ftimer[i1] = time(&ttmp);
  226.     fseq[i1] = swu;
  227.     swu = (1 + swu) % MAXSEQ;        /* bump send window */
  228.     nbuffers++;
  229.     npkt++;
  230.  
  231.     /* send it */
  232.     gspack(DATA, rwl, fseq[i1], outlen[i1], outbuf[i1]);
  233.  
  234.     /*
  235.      *    send it once then let the pkt machine take it.
  236.      *    wouldn't need this for multitasking systems
  237.     sl = gmachine();
  238.      */
  239.     return(0);
  240. }
  241.  
  242. /************     packet machine   ****** RH Lamb 3/87 */
  243. /*
  244.  *    Ideally we would like to fork this process off in an infinite loop
  245.  *    and send and receive pkts thru "inbuf" and "outbuf".  Can't do this in
  246.  *    MS-DOS so we setup "getpkt" and "sendpkt" to call this routine often
  247.  *    and return only when the input buffer is empty thus "blocking" the
  248.  *    pkt-machine task.
  249.  */
  250.  
  251. gmachine()
  252. {
  253.     int    rack, rseq, rlen, i1, i2, dflg;
  254.     char    rdata[PKTSIZE+1];
  255.     long    ttmp, itmp;
  256. #ifdef FJE
  257.     short time_err = 0;
  258. #endif /* FJE */
  259.  
  260. reply:
  261.     printmsg( 6, "*send %d<W<%d, rec %d<W<%d, err %d",
  262.         swl, swu, rwl, rwu, nerr );
  263.  
  264.     /*
  265.      *    waiting for ACKs for swl to swu-1.  Next pkt to send=swu
  266.      *    rwl=expected pkt
  267.      */
  268.     if (nerr >= MAXERR)
  269.         goto close;
  270.     dflg = 0;
  271.     switch (grpack(&rack, &rseq, &rlen, rdata)) {
  272.     case CLOSE:
  273.         printmsg( 5, "**got CLOSE");
  274.         goto close;
  275.     case NAK:
  276.         nerr++;
  277. #ifdef FJE
  278.         time_err = 0;
  279. #endif /* FJE */
  280.         acktmr = naktmr = 0;            /* stop ack/nak timer */
  281.         printmsg( 5, "**got NAK %d", rack );
  282. nloop:
  283.         if (between(swl, rack, swu)) {    /* resend rack->(swu-1) */
  284.             i1 = rack;
  285.             gspack(DATA, rwl, rack, outlen[i1], outbuf[i1]);
  286.             printmsg( 5, "***resent %d", rack );
  287.             ftimer[i1] = time(&ttmp);
  288.             rack = (1 + rack) % MAXSEQ;
  289.             goto nloop;
  290.         }
  291.         if (dflg)
  292.             return(POK);
  293.         goto reply;                        /* any other stuff ? */
  294.  
  295.     case EMPTY:
  296.         printmsg( 5, "**got EMPTY" );
  297.         itmp = time(&ttmp);
  298.         if (acktmr)
  299.             if ((itmp - acktmr) >= TIMEOUT) {    /* ack timed out */
  300.                 gspack(ACK, rwl, 0, 0, rdata);
  301. #ifdef FJE
  302.                 time_err++;
  303. #endif /* FJE */
  304.                 acktmr = itmp;
  305.             }
  306.         if (naktmr)
  307.             if ((itmp - naktmr) >= TIMEOUT) {    /* nak timed out */
  308.                 gspack(NAK, rwl, 0, 0, rdata);
  309. #ifdef FJE
  310.                 time_err++;
  311. #endif /* FJE */
  312.                 naktmr = itmp;
  313.             }
  314.         /* resend any timed out un-acked pkts */
  315. #ifdef FJE
  316.         /*
  317.          *    Wait up to 5 minutes.
  318.          */
  319.         if (time_err > 300 / TIMEOUT) {
  320.             printmsg( 0, "too many timeouts; closing connection" );
  321.             goto close;
  322.         }
  323. #endif /* FJE */
  324.         for (i2 = swl; between(swl, i2, swu); i2 = (1 + i2) % MAXSEQ)  {
  325.             acktmr = naktmr = 0;            /* reset ack/nak */
  326.             i1 = i2;
  327.             printmsg( 5, "--->seq,elapst %d %ld", i2, (itmp - ftimer[i1]) );
  328.             if ((itmp - ftimer[i1]) >= TIMEOUT) {
  329.                 printmsg( 5, "***timeout %d", i2 );
  330.                 /*
  331.                  *    since "g" is "go-back-N", when we time out we
  332.                  *    must send the last N pkts in order.  The generalized
  333.                  *    sliding window scheme relaxes this reqirement.
  334.                  */
  335.                 nerr++;
  336.                 dflg = 1;                    /* same hack */
  337.                 rack = i2;
  338.                 goto nloop;
  339.             }
  340.         }
  341.         return(POK);
  342.     case ACK:
  343. #ifdef FJE
  344.         time_err = 0;
  345. #endif /* FJE */
  346.         printmsg( 5, "**got ACK %d", rack );
  347.         acktmr = naktmr = 0;                /* disable ack/nak's */
  348. aloop:
  349.         if (between(swl, rack, swu)) {        /* S<-- -->(S+W-1)%8 */
  350.             printmsg( 5, "***ACK %d", swl );
  351.             ftimer[swl] = 0;
  352.             nbuffers--;
  353.             swl = (1 + swl) % MAXSEQ;
  354.             dflg = 1;                        /* same hack; sl */
  355.             goto aloop;
  356.         }
  357.         if (dflg)
  358.             return(POK);            /* hack for non-mutlitask systems */
  359.                                     /* to empty "inbuf[]" */
  360.         goto reply;
  361.     case DATA:
  362. #ifdef FJE
  363.         time_err = 0;
  364. #endif /* FJE */
  365.         printmsg( 5, "**got DATA %d %d", rack, rseq );
  366.         i1 = (1 + rwl) % MAXSEQ;            /* (R+1)%8 <-- -->(R+W)%8 */
  367.         i2 = (1 + rwu) % MAXSEQ;
  368.         if (between(i1, rseq, i2)) {
  369.             if (i1 == rseq) {
  370.                 i1 = rseq;
  371.                 arr[i1] = TRUE;
  372.                 inlen[i1] = rlen;
  373.                 memcpy(inbuf[i1], rdata, rlen);
  374.                 rwl = (rwl + 1) % MAXSEQ;
  375.                 printmsg( 5, "***ACK d %d", rwl );
  376.                 gspack(ACK, rwl, 0, 0, rdata);
  377.                 acktmr = time(&ttmp);        /* enable ack/nak tmout */
  378.                 dflg = 1;                    /* ret to call when finished */
  379.                                             /* (not in a multitask system) */
  380.             } else {
  381.                 nerr++;
  382.                 printmsg( 5, "***unexpected %d on %d", rseq, rwl );
  383.             }
  384.         } else {
  385.             nerr++;
  386.             printmsg( 5, "***wrong seq %d", rseq );
  387.         }
  388.         goto aloop;
  389.     case ERROR:
  390.         nerr++;
  391. #ifdef FJE
  392.         time_err = 0;
  393. #endif /* FJE */
  394.         printmsg( 5, "**got BAD CHK" );
  395.         gspack(NAK, rwl, 0, 0, rdata);
  396.         naktmr = time(&ttmp);                    /* set nak timer */
  397.         printmsg( 5, "***NAK d %d", rwl );
  398.         goto reply;
  399.     default:
  400.         printmsg( 5, "**got SCREW UP" );
  401.         goto reply;                                /* ignore it */
  402.     }
  403. close:
  404.     gspack(CLOSE, 0, 0, 0, rdata);
  405.     return(CLOSE);
  406. }
  407.  
  408. /*************** FRAMING *****************************/
  409. /*
  410.  *    send a packet
  411.  *
  412.  *    nt2=type nt3=pkrec nt4=pksent
  413.  *        len=length<=PKTSIZE cnt1= data * ret(0) always
  414.  */
  415. gspack(nt2, nt3, nt4, len, cnt1)
  416. int    nt2, nt3, nt4, len;
  417. char    cnt1[];
  418. {
  419.     unsigned int    check, i;
  420.     unsigned char    c2, pkt[HDRSIZE+1], dpkerr[10];
  421.     if (len > 64)
  422.         len = 64;
  423.     if (len == 0)
  424.         cnt1[0] = '\0';
  425. #if 0
  426.     /**Link testing mods- create artificial errors ***/
  427.     printf("**n:normal,e:error,l:lost,p:partial,h:bad header,s:new seq--> ");
  428.     gets(dpkerr);
  429.     if(dpkerr[0] == 's') { sscanf(&dpkerr[1],"%d",&nt4); }
  430.     /** End Link testing mods ***/
  431. #endif
  432.  
  433.     printmsg( 5, "send packet type %d, num=%d, n=%d, len=%d",
  434.         nt2, nt3, nt4, len );
  435.     printmsg( 5, "data =\n|%s|", cnt1 );
  436.     c2 = '\0';
  437.     pkt[0] = '\020';
  438.     pkt[4] = nt2 << 3;
  439.     nt2 &= 7;
  440.     switch (nt2) {
  441.     case 1:
  442.         break;                  /* stop protocol */
  443.     case 2:
  444.         pkt[4] += nt3;
  445.         break;                    /* reject        */
  446.     case 3:
  447.         break;
  448.     case 4:
  449.         pkt[4] += nt3;
  450.         break;                    /* ack          */
  451.     case 5:
  452.         pkt[4] += SWINDOW;
  453.         break;                    /* 3 windows */
  454.     case 6:
  455.         pkt[4] += 1;
  456.         break;                    /* pktsiz = 64 (1) */
  457.     case 7:
  458.         pkt[4] += SWINDOW;
  459.         break;                    /* 3 windows */
  460.     case 0:
  461.         pkt[4] += 0x80 + nt3 + (nt4 << 3);
  462.         c2 = (PKTSIZE - len) & 0xff;
  463.         /*
  464.          *    haven't set it up for VERY LONG pkts with a few
  465.          *    bytes yet (-128)
  466.          */
  467.         if (c2) {                        /* short packet handling */
  468.             pkt[4] += 0x40;                /* if len < PKTSIZE */
  469.             for (i = PKTSIZE - 1; i > 0; i--)
  470.                 cnt1[i] = cnt1[i-1];
  471.             cnt1[0] = c2;
  472.         }
  473.         break;
  474.     }
  475.     pkt[4] &= 0xff;
  476.     if (nt2) {
  477.         pkt[1] = 9;                        /* control packet size = 0 (9) */
  478.         check = (0xaaaa - pkt[4]) & 0xffff;
  479.     } else {
  480.         pkt[1] = PKTSIZ2;                /* data packet size = 64 (2) */
  481.         check = checksum(cnt1, PKTSIZE);
  482.         i = pkt[4];                        /* req'd on PC for XOR high bits */
  483.         i &= 0xff;
  484.         check = (check ^ i) & 0xffff;
  485.         check = (0xaaaa - check) & 0xffff;
  486.     }
  487.     pkt[2] = check & 0xff;
  488.     pkt[3] = (check >> 8) & 0xff;
  489.     pkt[5] = (pkt[1] ^ pkt[2] ^ pkt[3] ^ pkt[4]) & 0xff;
  490.  
  491. #if 0
  492.     /*** More Link testing MODS ******/
  493.     switch(dpkerr[0]) {
  494.     case 'e':   cnt1[10] = -cnt1[10];
  495.                 break;
  496.     case 'h':    pkt[5] = -pkt[5];
  497.                 break;
  498.     case 'l':    return;
  499.     case 'p':    swrite(pkt,HDRSIZE);
  500.                 if(pkt[1] != 9) swrite(cnt1,PKTSIZE-3);
  501.                 return;
  502.     default:    break;
  503.     }
  504.     /****** End Link Testing Mods **********/
  505. #endif
  506.  
  507.     swrite(pkt, HDRSIZE);            /* header is 6-bytes long */
  508. #if 0
  509.     write(flog,pkt,HDRSIZE);
  510. #endif
  511.     if (pkt[1] != 9) {
  512.         swrite(cnt1, PKTSIZE);        /* data is always 64 bytes long */
  513. #if 0
  514.         write(flog,cnt1,PKTSIZE);
  515. #endif
  516.     }
  517. }
  518.  
  519.  
  520. /*
  521.  *    read packet
  522.  *
  523.  *    on return: nt3=pkrec nt4=pksent
  524.  *        len=length<=PKTSIZE  cnt1=data * ret(type) ok;
  525.  *        ret(EMPTY) input buf empty;
  526.  *        ret(ERROR) bad header;
  527.  *        ret(EMPTY) lost pkt timeout;
  528.  *        ret(ERROR) checksum error;
  529.  *        ret(-5) ?
  530.  *
  531.  *    NOTE:
  532.  *
  533.  * sread(buf,n,timeout)
  534.  *    while(TRUE) {
  535.  *        if(# of chars available >= n) (without dec internal counter)
  536.  *            read n chars into buf (decrement internal char counter)
  537.  *            break
  538.  *        else
  539.  *            if(time>timeout) break
  540.  *    }
  541.  *    return(# of chars available)
  542.  */
  543.  
  544. grpack(nt3, nt4, len, cnt1)
  545. int    *nt3, *nt4, *len;
  546. char    cnt1[];
  547. {
  548.     unsigned int    nt1, check, checkchk, i;
  549.     unsigned char    c, c2;
  550.     int    ii;
  551.  
  552. #ifdef FJE
  553.     Chk_Abort(0L);
  554. #endif /* FJE */
  555.  
  556.     if (GOT_SYNC)
  557.         goto get_hdr;
  558.     if (GOT_HDR)
  559.         goto get_data;
  560.     c = '\0';
  561.     while ((c & 0x7f) != '\020')
  562.         if (sread(&c, 1, timeout) == 0)
  563.             return(EMPTY);
  564.     GOT_SYNC = TRUE;
  565. get_hdr:
  566.     if (sread(&grpkt[1], HDRSIZE - 1, timeout) < (HDRSIZE - 1))
  567.         return(EMPTY);
  568.     GOT_SYNC = FALSE;
  569. #if 0
  570.     i = grpkt[1] ^ grpkt[2] ^ grpkt[3] ^ grpkt[4] ^ grpkt[5];
  571. #else
  572.      i = (unsigned)grpkt[1] ^ (unsigned)grpkt[2] ^
  573.          (unsigned)grpkt[3] ^ (unsigned)grpkt[4] ^
  574.          (unsigned)grpkt[5];
  575. #endif
  576.     i &= 0xff;
  577.     printmsg( 10, "prpkt %02x %02x %02x %02x %02x .. %02x ",
  578.         grpkt[1], grpkt[2], grpkt[3], grpkt[4], grpkt[5], i);
  579.  
  580.     if (i) {
  581.         printmsg( 0, "**** bad header ****" );
  582.         /*
  583.          *    I'm not sure whether "g" considers it an empty or error
  584.          */
  585.         return(ERROR);
  586.     }
  587.     GOT_HDR = TRUE;
  588.     if ((grpkt[1] &= 0x7f) == 9) {            /* control packet */
  589.         *len = 0;
  590.         c = grpkt[4] & 0xff;
  591.         nt1  = c >> 3;
  592.         *nt3 = c & 7;
  593.         *nt4 = 0;
  594.         check = 0;
  595.         checkchk = 0;
  596.         cnt1[*len] = '\0';
  597.         GOT_HDR = FALSE;
  598.     } else {                                /* data packet */
  599.         if (grpkt[1] != PKTSIZ2)
  600.             return(-5);                    /* can't handle other than 64 */
  601. get_data:
  602.         if (sread(cnt1, PKTSIZE, timeout) < PKTSIZE)
  603.             return(EMPTY);
  604.         GOT_HDR = FALSE;
  605.         nt1  = 0;
  606.         c2 = grpkt[4] & 0xff;
  607.         c = c2 & 0x3f;
  608.         *nt4 = c >> 3;
  609.         *nt3 = c & 7;
  610.         i = grpkt[3];
  611.         i = (i << 8) & 0xff00;
  612.         check = grpkt[2];
  613.         check = i | (check & 0xff);
  614.         checkchk = checksum(cnt1, PKTSIZE);
  615.         i = grpkt[4] | 0x80;
  616.         i &= 0xff;
  617.         checkchk = 0xaaaa - (checkchk ^ i);
  618.         checkchk &= 0xffff;
  619.         if (checkchk != check) {
  620.             printmsg( 4, "*** checksum error ***" );
  621.             return(ERROR);
  622.         }
  623.         *len = PKTSIZE;
  624.         /*
  625.          *    haven't set it up for very long pkts yet (>128) RH Lamb
  626.          */
  627.         if (c2 & 0x40) {
  628.             ii = (cnt1[0] & 0xff);
  629.             *len = (*len - ii) & 0xff;
  630.             for (ii = 0; ii < *len; ii++)
  631.                 cnt1[ii] = cnt1[ii+1];
  632.         }
  633.         cnt1[*len] = '\0';
  634.     }
  635.     printmsg( 5, "rec  packet type %d, num=%d, n=%d, len=%d",
  636.         nt1, *nt3, *nt4, *len);
  637.     printmsg( 6, "  checksum rec = %x comp = %x, data=\n|%s|",
  638.         check, checkchk, cnt1);
  639.     ii = nt1;
  640.     return(ii);
  641. }
  642.  
  643.  
  644. unsigned checksum(data, len)
  645. int    len;
  646. char data[];
  647. {
  648.     unsigned int    i, j, tmp, chk1, chk2;
  649.     chk1 = 0xffff;
  650.     chk2 = 0;
  651.     j = len;
  652.     for (i = 0; i < len; i++) {
  653.         if (chk1 & 0x8000) {
  654.             chk1 <<= 1;
  655.             chk1++;
  656.         } else {
  657.             chk1 <<= 1;
  658.         }
  659.         tmp = chk1;
  660.         chk1 += (data[i] & 0xff);
  661.         chk2 += chk1 ^ j;
  662.         if ((chk1 & 0xffff) <= (tmp & 0xffff))
  663.             chk1 ^= chk2;
  664.         j--;
  665.     }
  666.     return(chk1 & 0xffff);
  667. }
  668.  
  669.  
  670. /*
  671.  *    gwrmsg
  672.  *    send a null terminated string out
  673.  */
  674. gwrmsg( typ, buf )
  675. char typ;
  676. char *buf;                    /* null terminated */
  677. {
  678.     return( 0 );
  679. }
  680.  
  681. /*
  682.  *    grdmsg
  683.  *    read a null terminated string
  684.  */
  685. grdmsg( buf )
  686. char *buf;
  687. {
  688.     return( 0 );
  689. }
  690.  
  691. /*
  692.  *    gwrdata
  693.  *    read a file and send it out
  694.  */
  695. gwrdata( f )
  696. {
  697.     return( 0 );
  698. }
  699.  
  700. /*
  701.  *    grrdata
  702.  *    read in data and send to file
  703.  */
  704. grrdata( f )
  705. {
  706.     return( 0 );
  707. }
  708.  
  709.  
  710. /*
  711.  *    grdblk
  712.  *    read a block of data in
  713.  */
  714. grdblk( blk, len )
  715. {
  716.     return( 0 );
  717. }
  718.  
  719. /*
  720.  *    gwrblk
  721.  *    write out a block of data
  722.  */
  723. gwrblk( blk, len )
  724. {
  725.     return( 0 );
  726. }
  727.